// 导入axios
import axios from 'axios'

// 导入完整组件库之后，如果组件是jsAPI类型的组件，仍然需要先导入后使用，如果组件当做标签使用，不需要特意导入直接使用
// 从vant组件库按需导入Toast轻提示
import { Toast } from 'vant'
// 导入 router
import router from '../router/index'
// 导入vuex的store模块
import store from '../store/index.js'
console.log('store', store)
// 线上地址
// const root = 'http://www.liulongbin.top:8000'
// 线下地址
const root = 'http://192.168.141.47:8000'
// 调用 axios.create() 方法，创建 axios 的实例对象
const request = axios.create({
  // 请求根路径
  baseURL: root
})
// 1、拦截器的挂载一定要放到request实例创建之后
// 2、由于我们在项目中是基于request实例对象发起的请求，因此拦截器一定要挂载给request而不是axios

// 展示loading写1次，隐藏写3次
// 添加请求拦截器
// 在请求拦截器的第一个function中形参config就是每次请求时候的配置选项
request.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  // 展示loading效果
  Toast.loading({
    message: '加载中...',
    // 展示时长(ms)，值为 0 时，toast 不会自动关闭
    duration: 0
  })
  // 从vuex中获取token的值
  const tokenStr = store.state.tokenInfo.token
  if (tokenStr) {
    // 只有tokenStr存在的时候才有必要挂载到请求头Authorization属性中
    config.headers.Authorization = 'Bearer ' + tokenStr
  }

  return config
}, function (error) {
  // 对请求错误做些什么
  // 隐藏loading效果
  Toast.clear()
  return Promise.reject(error)
})

// 添加响应拦截器
request.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    // 隐藏loading效果
    Toast.clear()

    return response
  },
  async function (error) {
    // 对响应错误做点什么
    // 隐藏loading效果
    Toast.clear()
    // 从vuex中获取refresh_token的值
    const refreshToken = store.state.tokenInfo.refresh_token
    // 判断响应状态码为401 ，如果refresh_token有值且状态码为401 应该执行换区token的操作
    if (error.response.status === 401 || refreshToken) {
      console.log('执行换取token的操作')
      try {
        // 大坑1：千万不要在这里直接使用request对象来发起换取token的请求（请求拦截器会把refresh_token换成过期的token值），直接用axios发起请求（axios没有挂载请求拦截器）
        const { data: res } = await axios({
          method: 'PUT',
          // 大坑2：使用axios发起请求是一定要给定完整的url地址，因为axios没有配置baseURL
          url: root + '/v1_0/authorizations',
          headers: {
            // 大坑3：Authorization的值格式必须为Bearer xxx
            Authorization: 'Bearer ' + refreshToken
          }
        })
        console.log('token换取成功')
        console.log(res)
        // 1、用新token替换vuex和localStorage中的旧token refresh_token还是原来的refresh_token，
        store.commit('updateTokenInfo', { token: res.data.token, refresh_token: refreshToken })
        // 2、继续完成上次失败的请求
        // (1)请求的method是什么
        // (2)url地址是什么
        // (3)请求参数是什么
        return request(error.config)
      } catch {
        // 只要能执行到catch，证明token和refresh_token都过期了
        store.commit('cleanState')
        // 强制跳转到登录页
        router.replace('/login?pre=' + router.currentRoute.fullPath)
      }
    }

    return Promise.reject(error)
  })

// 共享
export default request
